package cn.cttic.order.service.impl;

import cn.cttic.app.api.enums.InstallOrderStatus;
import cn.cttic.app.api.enums.SaleOrderStatus;
import cn.cttic.base.api.RemoteBaseDeviceInfoService;
import cn.cttic.base.api.RemoteBaseRecordService;
import cn.cttic.base.api.domain.BaseRecord;
import cn.cttic.base.api.domain.BaseUser;
import cn.cttic.base.api.domain.bo.BaseRecordBo;
import cn.cttic.base.api.domain.vo.BaseDeviceInfoVo;
import cn.cttic.base.api.domain.vo.BaseRecordVo;
import cn.cttic.common.core.exception.link.LinkException;
import cn.cttic.common.core.exception.order.OrderException;
import cn.cttic.common.core.utils.BeanCopyUtils;
import cn.cttic.common.core.utils.MapstructUtils;
import cn.cttic.common.core.utils.StringUtils;
import cn.cttic.common.mybatis.core.page.TableDataInfo;
import cn.cttic.common.mybatis.core.page.PageQuery;
import cn.cttic.common.satoken.utils.AppLoginHelper;
import cn.cttic.common.satoken.utils.LoginHelper;
import cn.cttic.link.api.RemoteThirdInterfaceService;
import cn.cttic.link.api.domain.vo.BaseThirdInterfaceVo;
import cn.cttic.link.api.domain.vo.DistributeDevicePosisitionVo;
import cn.cttic.link.api.domain.vo.GisTimePosistionVo;
import cn.cttic.link.api.domain.vo.ThirdDistributeR;
import cn.cttic.order.api.domain.BaseInstallOrderMainPage;
import cn.cttic.order.api.domain.BaseInstallOrderProcess;
import cn.cttic.order.api.domain.BaseSaleOrder;
import cn.cttic.order.api.domain.bo.*;
import cn.cttic.order.api.domain.vo.*;
import cn.cttic.order.mapper.BaseInstallOrderProcessMapper;
import cn.cttic.order.mapper.BaseSaleOrderMapper;
import cn.cttic.system.api.model.LoginUser;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import cn.cttic.order.api.domain.BaseInstallOrder;
import cn.cttic.order.mapper.BaseInstallOrderMapper;
import cn.cttic.order.service.IBaseInstallOrderService;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 安装订单Service业务层处理
 *
 * @author Times.Studio
 * @date 2024-09-17
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class BaseInstallOrderServiceImpl implements IBaseInstallOrderService {

    private final BaseInstallOrderMapper baseMapper;

    private final BaseSaleOrderMapper baseSaleMapper;

    private final BaseInstallOrderProcessMapper baseInstallOrderProcessMapper;

    @DubboReference
    private RemoteBaseRecordService remoteBaseRecordService;

    @DubboReference
    private RemoteBaseDeviceInfoService remoteBaseDeviceInfoService;

    @DubboReference
    private RemoteThirdInterfaceService remoteThirdInterfaceService;

    /**
     * 查询安装订单
     *
     * @param id 主键
     * @return 安装订单
     */
    @Override
    public BaseInstallOrderVo queryById(String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询订单验收详情
     *
     * @param id 订单ID
     * @return
     */
    @Override
    public InstallOrderVerifyVo queryVerifyDetailById(String id) {
        InstallOrderVerifyVo vo = new InstallOrderVerifyVo();

        BaseInstallOrderVo installOrderVo = baseMapper.getInstallOrder4VerifyReview(
            new QueryWrapper<BaseInstallOrder>().eq("installOrder.id", id)
        );
        vo.setInstallOrderReactive(installOrderVo);

        InstallOrderVerifyInfoVo installOrderVerifyInfo = baseMapper.getInstallOrderVerifyInfo(id);
        vo.setInstallOrder(installOrderVerifyInfo);

        SaleOrderVerifyInfoVo saleOrderVerifyInfo = baseMapper.getSaleOrderVerifyInfo(id);
        vo.setSaleOrder(saleOrderVerifyInfo);

        List<BaseInstallOrderProcessVo> processVoList = baseInstallOrderProcessMapper.selectVoList(
            new LambdaQueryWrapper<BaseInstallOrderProcess>()
                .eq(BaseInstallOrderProcess::getInstallOrderId, id)
        );

        String imei = null;
        Optional<BaseInstallOrderProcessVo> ip = processVoList.stream().filter(x -> x.getStepId().equals("10010")).findFirst();
        if (ip.isPresent()) {
            imei = ip.get().getInteriorData();
        }

        BaseDeviceInfoVo baseDeviceInfoVo = remoteBaseDeviceInfoService.getBaseDeviceInfoByInstallOrderId(id);
        if (ObjectUtil.isEmpty(baseDeviceInfoVo)) {
            baseDeviceInfoVo = remoteBaseDeviceInfoService.getBaseDeviceInfoByIMEI(imei);
        }
        if (ObjectUtil.isNotEmpty(baseDeviceInfoVo)) {
            DeviceVerifyInfoVo deviceVerifyInfoVo = BeanCopyUtils.copy(baseDeviceInfoVo, DeviceVerifyInfoVo.class);

            if (StrUtil.isNotEmpty(installOrderVo.getOnlineInterfaceId())) {
                BaseThirdInterfaceVo interfaceVo = remoteThirdInterfaceService.getThirdInterfaceById(installOrderVo.getOnlineInterfaceId());
                deviceVerifyInfoVo.setCheckStatus("检测成功");
                deviceVerifyInfoVo.setCheckTime(installOrderVo.getOnlineTime());

                ThirdDistributeR<DistributeDevicePosisitionVo> r = JSON.parseObject(interfaceVo.getResponseBody(), new TypeReference<ThirdDistributeR<DistributeDevicePosisitionVo>>() {
                });
                DistributeDevicePosisitionVo distributeDevicePosisitionVo = r.getData();
                if (distributeDevicePosisitionVo != null && distributeDevicePosisitionVo.getLatitude() != null && distributeDevicePosisitionVo.getLongitude() != null) {
                    deviceVerifyInfoVo.setCheckPosition("(" + distributeDevicePosisitionVo.getLongitude() + "," + distributeDevicePosisitionVo.getLatitude() + ")");
                } else {
                    deviceVerifyInfoVo.setCheckPosition("无位置信息");
                }
            } else {
                deviceVerifyInfoVo.setCheckStatus("检测失败");
                deviceVerifyInfoVo.setCheckTime(installOrderVo.getStartTime());
                deviceVerifyInfoVo.setCheckPosition("(" + "," + ")");
            }
            vo.setDevice(deviceVerifyInfoVo);
        }

        Map<String, BaseInstallOrderProcessVo> map = processVoList.stream().collect(Collectors.toMap(BaseInstallOrderProcessVo::getStepId, Function.identity()));
        vo.setInstallOrderProcessMap(map);

        return vo;
    }

    /**
     * 查询安装订单信息
     *
     * @param id 主键
     * @return 安装订单
     */
    @Override
    public BaseInstallOrderVo getInstallOrderInfoById(String id) {
        return baseMapper.getInstallOrderInfo(id);
    }

    /**
     * 查询验收安装信息
     *
     * @param id 安装订单ID
     * @return
     */
    @Override
    public InstallOrderVerifyInfoVo queryInstallVerifyInfoByInstallOrderId(String id) {
        return baseMapper.getInstallOrderVerifyInfo(id);
    }

    /**
     * 查询验收销售信息
     *
     * @param id 安装订单ID
     * @return
     */
    @Override
    public SaleOrderVerifyInfoVo querySaleVerifyInfoByInstallOrderId(String id) {
        return baseMapper.getSaleOrderVerifyInfo(id);
    }

    /**
     * 分页查询安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {
        QueryWrapper<BaseInstallOrder> qw = buildInstallOrderQueryWrapper(bo);
        qw.orderByDesc("installOrder.create_time");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), qw);
        return TableDataInfo.build(result);
    }

    /**
     * 分页查询安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryInstalledPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {
        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        lqw.eq("installOrder.status", InstallOrderStatus.INSTALLED.getValue()).isNull("installOrder.received_user_id")
            .orderByDesc("installOrder.create_time");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 分页查询安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryReceivedPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();

        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        lqw.eq("installOrder.received_user_id", userId)
            .orderByDesc("installOrder.received_time")
            .orderByDesc("installOrder.status");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 分页查询已经验收的安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryVerifiedPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();

        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        lqw.eq("installOrder.status", InstallOrderStatus.FINISHED.getValue())
            .isNull("installOrder.review_user_id")
            .eq("installOrder.verify_status", 1)
            .orderByDesc("installOrder.verify_time")
            .orderByDesc("installOrder.status");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 分页查询已经验收的安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryReceived4ReviewPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();

        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        lqw.eq("installOrder.status", InstallOrderStatus.FINISHED.getValue())
            .eq("installOrder.verify_status", 1)
            .eq("installOrder.review_user_id", userId)
            .orderByDesc("installOrder.received_time")
            .orderByDesc("installOrder.status");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 分页查询安装订单列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 安装订单分页列表
     */
    @Override
    public TableDataInfo<BaseInstallOrderVo> queryCheckPageList(BaseInstallOrderQueryBo bo, PageQuery pageQuery) {

        LoginUser loginUser = LoginHelper.getLoginUser();
        Long userId = loginUser.getUserId();

        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        lqw.eq("installOrder.received_user_id", userId)
            .eq("installOrder.verify_status", 1)
            .orderByDesc("installOrder.received_time")
            .orderByDesc("installOrder.status");
        Page<BaseInstallOrderVo> result = baseMapper.getInstallOrderPageList(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的安装订单列表
     *
     * @param bo 查询条件
     * @return 安装订单列表
     */
    @Override
    public List<BaseInstallOrderVo> queryList(BaseInstallOrderQueryBo bo) {
        QueryWrapper<BaseInstallOrder> lqw = buildInstallOrderQueryWrapper(bo);
        return baseMapper.getInstallOrderList(lqw);
    }

    private QueryWrapper<BaseInstallOrder> buildInstallOrderQueryWrapper(BaseInstallOrderQueryBo bo) {
        QueryWrapper<BaseInstallOrder> qw = Wrappers.query();
        qw.eq("installOrder.del_flag", 0);
        qw.like(StringUtils.isNotBlank(bo.getSaleOrderId()), "saleOrder.id", bo.getSaleOrderId());
        qw.eq(StringUtils.isNotBlank(bo.getChannelType()), "company.channel_type", bo.getChannelType());
        qw.eq(StringUtils.isNotBlank(bo.getProductId()), "product.id", bo.getProductId());
        qw.eq(StringUtils.isNotBlank(bo.getDeviceId()), "device.id", bo.getDeviceId());
        qw.like(StringUtils.isNotBlank(bo.getLastName()), "saleOrder.last_name", bo.getLastName());
        qw.eq(bo.getGender() != null, "saleOrder.gender", bo.getGender());
        qw.like(StringUtils.isNotBlank(bo.getPhone()), "saleOrder.phone", bo.getPhone());
        qw.like(StringUtils.isNotBlank(bo.getCarNo()), "saleOrder.car_no", bo.getCarNo());
        qw.like(StringUtils.isNotBlank(bo.getInstallCode()), "installOrder.install_code", bo.getInstallCode());
        qw.eq(StringUtils.isNotBlank(bo.getSalesManId()), "saleOrder.id", bo.getSalesManId());
        qw.like(StringUtils.isNotBlank(bo.getInstallOrderId()), "installOrder.id", bo.getInstallOrderId());
        qw.eq(StringUtils.isNotBlank(bo.getInstallManId()), "installOrder.install_man_id", bo.getInstallManId());
        qw.eq(bo.getStatus() != null, "installOrder.status", bo.getStatus());
        qw.eq(bo.getActiveStatus() != null, "installOrder.active_status", bo.getActiveStatus());
        qw.eq(bo.getInstallStatus() != null, "installOrder.install_status", bo.getInstallStatus());
        qw.eq(bo.getVerifyStatus() != null, "installOrder.verify_status", bo.getVerifyStatus());
        qw.eq(bo.getCheckStatus() != null, "installOrder.check_status", bo.getCheckStatus());
        return qw;
    }

    /**
     * 签收订单(用于验收）
     *
     * @param orderId 订单号
     * @return
     */
    @Override
    public BaseInstallOrderVo receiveInstalledOrder(String orderId) {

        BaseInstallOrder order = baseMapper.selectById(orderId);
        if (order.getStatus() != InstallOrderStatus.INSTALLED.getValue()) {
            throw new OrderException(String.format("订单 %s 不处于安装完成状态", orderId));
        }

        order.setReceivedUserId(LoginHelper.getUserId());
        order.setReceivedTime(LocalDateTime.now());

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(orderId)
            .withActionType("订单验收")
            .withActionName("订单验收（签收）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult("验收（签收）完成")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[安装订单][订单验收] [验收（签收）记录] {}", recordVo);

        if (baseMapper.updateById(order) <= 0) {
            throw new OrderException(String.format("签收订单 %s 失败（更新）", orderId));
        }

        return baseMapper.selectVoById(orderId);
    }

    @Override
    public BaseInstallOrderVo verifyOrder(VerifyOrderBo bo) {
        BaseInstallOrder order = baseMapper.selectById(bo.getOrderId());

        order.setVerifyStatus(bo.getVerifyStatus());
        order.setVerifyReason(bo.getVerifyReason());
        order.setVerifyTime(LocalDateTime.now());
        order.setStatus(bo.getVerifyStatus() == 2 ? InstallOrderStatus.PROBLEM.getValue() : InstallOrderStatus.FINISHED.getValue());

        // 更新车牌号
        List<BaseInstallOrderProcess> processList = baseInstallOrderProcessMapper.selectList(
            new LambdaQueryWrapper<BaseInstallOrderProcess>()
                .eq(BaseInstallOrderProcess::getInstallOrderId, order.getId())
                .eq(BaseInstallOrderProcess::getStepId, "10015")
        );
        if (processList.size() != 1) {
            throw new OrderException(String.format("验收订单 %s 失败（更新车牌号）", bo.getOrderId()));
        }

        String strData = processList.get(0).getInteriorData();
        BaseInstallOrderMainPage mainPage = JSON.parseObject(strData, BaseInstallOrderMainPage.class);
        if (ObjUtil.isEmpty(mainPage) || StrUtil.isBlank(mainPage.getCarNo())) {
            throw new OrderException(String.format("验收订单 %s 失败（驾驶证车牌号未找到）", bo.getOrderId()));
        }
        order.setCarNo(mainPage.getCarNo());

        if (bo.getVerifyStatus() == 1) {
            BaseSaleOrder saleOrder = baseSaleMapper.selectById(order.getSaleOrderId());
            saleOrder.setStatus(SaleOrderStatus.ACCEPTED.getValue());
            int ret = baseSaleMapper.updateById(saleOrder);
            if (ret <= 0) {
                throw new OrderException(String.format("验收订单 %s 失败（更新销售单）", bo.getOrderId()));
            }
        }

        List<BaseInstallOrderProcessVo> processVoList = baseInstallOrderProcessMapper.selectVoList(
            new LambdaQueryWrapper<BaseInstallOrderProcess>().eq(BaseInstallOrderProcess::getInstallOrderId, order.getId())
        );
        int index = 1;
        String reasonPlus = "";
        for (BaseInstallOrderProcessVo processVo : processVoList) {
            if (processVo.getAuditStatus() == 2) {
                String stepName = "安装步骤";
                if (processVo.getStepId().equals("10010")) {
                    stepName = "采集IMEI数据";
                } else if (processVo.getStepId().equals("10015")) {
                    stepName = "采集行驶证正页";
                } else if (processVo.getStepId().equals("10020")) {
                    stepName = "采集行驶证副页";
                } else if (processVo.getStepId().equals("10025")) {
                    stepName = "采集车身照";
                } else if (processVo.getStepId().equals("10030")) {
                    stepName = "采集接线前线路照片";
                } else if (processVo.getStepId().equals("10035")) {
                    stepName = "采集安装位置照片";
                } else if (processVo.getStepId().equals("10040")) {
                    stepName = "采集接线后线路照片";
                } else if (processVo.getStepId().equals("10045")) {
                    stepName = "采集里程表照片";
                }
                String reason = StrUtil.isEmpty(processVo.getAuditReason()) ? "" : ("原因： " + processVo.getAuditReason());
                reasonPlus += String.format("%d - %s 审核不通过 %s;", index++, stepName, reason);
            }
        }

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(bo.getOrderId())
            .withActionType("订单验收")
            .withActionName("订单验收")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult(bo.getVerifyStatus() == 1 ? "验收通过" : "验收未通过")
            .withActionResultContent((StrUtil.isEmpty(bo.getVerifyReason()) ? "" : bo.getVerifyReason()) + " [详细][ " + reasonPlus + " ]")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[安装订单][订单验收] [验收记录] {}", recordVo);

        if (baseMapper.updateById(order) > 0) {
            return baseMapper.selectVoById(bo.getOrderId());
        } else {
            throw new OrderException(String.format("验收订单 %s 失败（更新）", bo.getOrderId()));
        }
    }

    /**
     * 签收订单（订单质控）
     *
     * @param orderId
     * @return
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public BaseInstallOrderVo receiveVerifiedOrder(String orderId) {
        log.info("[安装订单][QC签收] {} [开始]", orderId);

        // 获取安装订单
        BaseInstallOrder order = baseMapper.selectById(orderId);

        // 核验状态
        if (order.getStatus() != InstallOrderStatus.FINISHED.getValue()) {
            log.error("[安装订单][QC签收] {} [失败 => 不处于验收完成状态]", orderId);
            throw new OrderException(String.format("订单 %s 不处于验收完成状态", orderId));
        }

        // 签收
        order.setReviewUserId(LoginHelper.getUserId());
        order.setReviewReceiveTime(LocalDateTime.now());
        if (baseMapper.updateById(order) <= 0) {
            log.error("[安装订单][QC签收] {} [失败 => 无法更新数据库]", orderId);
            throw new OrderException(String.format("签收订单 %s 失败（更新）", orderId));
        }

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(orderId)
            .withActionType("订单验收")
            .withActionName("订单品控（签收）")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult("签收完成")
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[安装订单][QC签收] [签收记录] {}", recordVo);

        log.info("[安装订单][QC签收] {} [完成]", orderId);
        return baseMapper.selectVoById(orderId);
    }

    /**
     * 复核订单
     *
     * @param bo 订单质控信息
     * @return
     */
    @Override
    public BaseInstallOrderVo reviewVerifiedOrder(ReviewOrderBo bo) {
        log.info("[安装订单][QC] {} [开始]", bo);
        BaseInstallOrder order = baseMapper.selectById(bo.getOrderId());

        // QC 未通过, 打回
        if (bo.getReviewStatus() == 2) {
            order.setVerifyStatus(2);
            order.setStatus(InstallOrderStatus.PROBLEM.getValue());
        }

        // 更新状态及内容
        order.setReviewStatus(bo.getReviewStatus());
        order.setReviewReason(bo.getReviewReason());
        order.setReviewTime(LocalDateTime.now());
        if (baseMapper.updateById(order) <= 0) {
            log.error("[安装订单][QC] {} [失败 => 无法更新数据库]", bo.getOrderId());
            throw new OrderException(String.format("订单QC %s 无法更新数据库", bo.getOrderId()));
        }

        // 记录事件
        BaseRecord.BaseRecordBuilder baseRecordBuilder = BaseRecord.BaseRecordBuilder.aBaseRecord();
        BaseRecord baseRecord = baseRecordBuilder.withBusinessId(bo.getOrderId())
            .withActionType("订单验收")
            .withActionName("订单质控")
            .withActionOperator(LoginHelper.getLoginUser().getNickname() + "(" + LoginHelper.getDeptName() + "-" + LoginHelper.getLoginUser().getPhone() + ")")
            .withActionTime(new Date())
            .withActionResult(bo.getReviewStatus() == 1 ? "质控通过" : "质控未通过")
            .withActionResultContent(bo.getReviewReason())
            .build();
        BaseRecordVo recordVo = remoteBaseRecordService.addRecord(BeanCopyUtils.copy(baseRecord, BaseRecordBo.class));
        log.info("[安装订单][QC签收] [签收记录] {}", recordVo);

        log.info("[安装订单][QC] {} [完成]", bo.getOrderId());
        return baseMapper.selectVoById(bo.getOrderId());
    }

    @Override
    public BaseInstallOrderVo checkOrder(VerifyOrderBo bo) {
        BaseInstallOrder order = baseMapper.selectById(bo.getOrderId());

        order.setStatus(InstallOrderStatus.VERIFICATED.getValue());
        order.setInstallStatus(1);
        order.setVerifyReason(bo.getVerifyReason());

        if (baseMapper.updateById(order) > 0) {
            return baseMapper.selectVoById(bo.getOrderId());
        } else {
            throw new OrderException(String.format("核销订单 %s 失败（更新）", bo.getOrderId()));
        }
    }

    @Override
    public BaseInstallOrderVo resetOrder(String orderId) {
        BaseInstallOrder order = baseMapper.selectById(orderId);

        BaseSaleOrder saleOrder = baseSaleMapper.selectById(order.getSaleOrderId());

        LambdaUpdateWrapper<BaseInstallOrder> installOrderUpdateWrapper = new LambdaUpdateWrapper<BaseInstallOrder>();
        installOrderUpdateWrapper.set(BaseInstallOrder::getStatus, InstallOrderStatus.WAITING.getValue());
        installOrderUpdateWrapper.set(BaseInstallOrder::getInstallStatus, 0);
        installOrderUpdateWrapper.set(BaseInstallOrder::getVerifyStatus, 0);
        installOrderUpdateWrapper.set(BaseInstallOrder::getActiveStatus, 0);
        installOrderUpdateWrapper.set(BaseInstallOrder::getVerifyReason, null);
        installOrderUpdateWrapper.set(BaseInstallOrder::getReceivedUserId, null);
        installOrderUpdateWrapper.set(BaseInstallOrder::getInstallManId, null);
        installOrderUpdateWrapper.set(BaseInstallOrder::getImei, null);
        installOrderUpdateWrapper.eq(BaseInstallOrder::getId, orderId);
//        order.setStatus(
//        order.setInstallStatus(0);
//        order.setVerifyStatus(0);
//        order.setActiveStatus(0);
//        order.setVerifyReason("");
//        order.setReceivedUserId(null);
//        order.setReviewUserId(null);
//        order.setInstallManId("");
//        order.setImei("");
        if (StrUtil.isBlank(saleOrder.getCarNo())) {
            order.setCarNo(null);
            installOrderUpdateWrapper.set(BaseInstallOrder::getCarNo, null);
        } else {
            order.setCarNo(saleOrder.getCarNo());
            installOrderUpdateWrapper.set(BaseInstallOrder::getCarNo, saleOrder.getCarNo());
        }

        Long cnt = baseInstallOrderProcessMapper.selectCount(new LambdaQueryWrapper<BaseInstallOrderProcess>().eq(BaseInstallOrderProcess::getInstallOrderId, orderId));

        if (cnt > 0) {
            if (baseInstallOrderProcessMapper.delete(
                new LambdaQueryWrapper<BaseInstallOrderProcess>().eq(BaseInstallOrderProcess::getInstallOrderId, orderId)
            ) <= 0) {
                throw new OrderException(String.format("重置订单 %s 失败（清理安装信息）", orderId));
            }
        }

        saleOrder.setStatus(SaleOrderStatus.WAITING.getValue());
        if (baseSaleMapper.updateById(saleOrder) <= 0) {
            throw new OrderException(String.format("重置订单 %s 失败（更新销售订单）", orderId));
        }

        if (baseMapper.update(installOrderUpdateWrapper) > 0) {
            return baseMapper.selectVoById(orderId);
        } else {
            throw new OrderException(String.format("重置订单 %s 失败（更新）", orderId));
        }
    }

    private LambdaQueryWrapper<BaseInstallOrder> buildQueryWrapper(BaseInstallOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BaseInstallOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getSaleOrderId()), BaseInstallOrder::getSaleOrderId, bo.getSaleOrderId());
        lqw.eq(StringUtils.isNotBlank(bo.getCarNo()), BaseInstallOrder::getCarNo, bo.getCarNo());
        lqw.eq(StringUtils.isNotBlank(bo.getInstallCode()), BaseInstallOrder::getInstallCode, bo.getInstallCode());
        lqw.eq(StringUtils.isNotBlank(bo.getInstallUrl()), BaseInstallOrder::getInstallUrl, bo.getInstallUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getInstallManId()), BaseInstallOrder::getInstallManId, bo.getInstallManId());
        lqw.eq(StringUtils.isNotBlank(bo.getNoticeSmsId()), BaseInstallOrder::getNoticeSmsId, bo.getNoticeSmsId());
        lqw.eq(bo.getNoticeStatus() != null, BaseInstallOrder::getNoticeStatus, bo.getNoticeStatus());
        lqw.eq(bo.getStatus() != null, BaseInstallOrder::getStatus, bo.getStatus());
        lqw.eq(bo.getInstallStatus() != null, BaseInstallOrder::getInstallStatus, bo.getInstallStatus());
        lqw.eq(bo.getActiveStatus() != null, BaseInstallOrder::getActiveStatus, bo.getActiveStatus());
        lqw.eq(bo.getVerifyStatus() != null, BaseInstallOrder::getVerifyStatus, bo.getVerifyStatus());
        return lqw;
    }

    /**
     * 新增安装订单
     *
     * @param bo 安装订单
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(BaseInstallOrderBo bo) {
        BaseInstallOrder add = MapstructUtils.convert(bo, BaseInstallOrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改安装订单
     *
     * @param bo 安装订单
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(BaseInstallOrderBo bo) {
        BaseInstallOrder update = MapstructUtils.convert(bo, BaseInstallOrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BaseInstallOrder entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除安装订单信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
